package com.lwf.fatapi.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.lwf.fatapi.dto.LoginRequest;
import com.lwf.fatapi.entities.SysPermission;
import com.lwf.fatapi.entities.SysRole;
import com.lwf.fatapi.entities.SysUser;
import com.lwf.fatapi.exception.BusinessException;
import com.lwf.fatapi.mapper.SysPermissionMapper;
import com.lwf.fatapi.mapper.SysRoleMapper;
import com.lwf.fatapi.service.AuthService;
import com.lwf.fatapi.service.SysUserService;
import com.lwf.fatapi.utils.PasswordUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 认证服务实现类
 *
 * @author lwf
 */
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysPermissionMapper permissionMapper;

    @Override
    public Map<String, Object> login(LoginRequest request) {
        // 查询用户
        SysUser user = userService.getUserByUsername(request.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }

        // 检查用户状态
        if (user.getStatus() == 0) {
            throw new BusinessException("账户已被禁用");
        }

        // 验证密码
        if (!PasswordUtils.matches(request.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }

        // 登录成功，生成token
        StpUtil.login(user.getId());

        // 获取token信息
        String token = StpUtil.getTokenValue();

        // 获取用户角色和权限
        List<SysRole> roles = roleMapper.selectRolesByUserId(user.getId());
        List<SysPermission> permissions = permissionMapper.selectPermissionsByUserId(user.getId());

        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", user);
        result.put("roles", roles);
        result.put("permissions", permissions.stream().map(SysPermission::getPermissionCode).collect(Collectors.toList()));

        return result;
    }

    @Override
    public boolean register(SysUser user) {
        // 检查用户名是否已存在
        if (userService.getUserByUsername(user.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        // 加密密码
        user.setPassword(PasswordUtils.encode(user.getPassword()));
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setStatus(1);
        user.setIsDeleted(0);

        // 这里需要实现用户注册逻辑
        // 暂时抛出异常，提示需要管理员创建用户
        throw new BusinessException("请联系管理员创建账户");
    }

    @Override
    public boolean logout() {
        StpUtil.logout();
        return true;
    }

    @Override
    public Map<String, Object> getCurrentUser() {
        if (!StpUtil.isLogin()) {
            throw new BusinessException("用户未登录");
        }

        Long userId = Long.valueOf(StpUtil.getLoginId().toString());
        SysUser user = userService.getUserById(userId);

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 获取用户角色和权限
        List<SysRole> roles = roleMapper.selectRolesByUserId(userId);
        List<SysPermission> permissions = permissionMapper.selectPermissionsByUserId(userId);

        Map<String, Object> result = new HashMap<>();
        result.put("user", user);
        result.put("roles", roles);
        result.put("permissions", permissions.stream().map(SysPermission::getPermissionCode).collect(Collectors.toList()));

        return result;
    }

    @Override
    public Map<String, Object> refreshToken() {
        if (!StpUtil.isLogin()) {
            throw new BusinessException("用户未登录");
        }

        // 刷新token
        StpUtil.renewTimeout(StpUtil.getTokenTimeout());
        String token = StpUtil.getTokenValue();

        Map<String, Object> result = new HashMap<>();
        result.put("token", token);

        return result;
    }
}
